// *************************************************************************************************
//
// MK3D Engine
// --------------------------------------
// Copyright (C) 2007-2011 Zeb (mailto: zebbey@gmail.com)
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// *************************************************************************************************

#ifndef __H_MK_REPR_TERRAIN_REGION__
#define __H_MK_REPR_TERRAIN_REGION__

#include "mk_entity.h"
#include "mk_terrain_region.h"
#include "mk_texture_mapping.h"

namespace MK3DE
{
	class CScene;
	class CTerrainRegion;
	class CTerrainHeightBrush;
	class CTerrainLayerBrush;
	class CTexture2D;
	class CShader;
	class CRenderInput;
	class CHardwareBuffer;
	class CEntityTerrain;

	class MK3DE_API CEntityTerrainRegion : public CEntity
	{
	public:
		CEntityTerrainRegion(CScene* pScene, CEntityTerrain* pEntityTerrain);
		~CEntityTerrainRegion();

		//! Get entity render type and entity type.
		ENTITY_RENDER_TYPE GetRenderType() { return ERT_SOLID; }
		ENTITY_TYPE GetType() { return ET_TERRAIN_REGION; }

		//! Create terrain region.
		BOOL Create(int regionX, int regionY, const char* shaderFileName);

		//! Load terrain region height from height map file.
		BOOL LoadHeightMap(const char* fileName);

		//! Save height to height map.
		BOOL SaveHeightMap(const char* fileName);

		//! Get position of terrain region mesh's vertex.
		BOOL GetVertexPosition(/* out */ D3DXVECTOR3& pos, DWORD x, DWORD y);

		//! Specified x,y in world coordinate and x,y in terrain region coordinate to get terrain ground height.
		BOOL GetGroundHeight(/* out */ float& height, float x, float y, float offsetX, float offsetY);

		//! Use a terrain height brush to paint terrain region's height.
		BOOL PaintHeight(CTerrainHeightBrush* brush);

		//! Get terrain region core object.
		CTerrainRegion* GetCoreTerrainRegion() { return _coreTerrainRegion; }

		//! Update position to vertex buffer.
		BOOL UpdatePositionVertexBuffer();

		//! Update normal to vertex buffer.
		BOOL UpdateNormalVertexBuffer();

		//! Update texture coordinate to vertex buffer.
		BOOL UpdateTextureCoordVertexBuffer();

		//! Update local axis align bounding box.
		void UpdateLocalAABB();

		//! Add a texture map and specified whether it's a terrain layer.
		BOOL AddTextureMap(const char* name, CTexture2D* pTexture, BOOL isLayer);

		//! Add a texture map and specified whether it's a terrain layer.
		BOOL AddTextureMapFromFile(const char* name, const char* fileName, BOOL isLayer);

		//! Save texture map.
		BOOL SaveTextureMap(const char* name, const char* fileName);

		//! Use a terrain layer brush to paint terrain layer blend weight.
		BOOL PaintLayer(CTerrainLayerBrush* brush, const char* fileName);

		//! Clear specified layer.
		BOOL ClearLayer(DWORD layer);

		//! Get layer count.
		DWORD GetLayerCount();

		//! Get layer texture mapping information.
		BOOL GetLayerMappingInfo(DWORD idx, /* out */ std::string& texName, /* out */ std::string& texFileName);

		//! Get mapping information.
		BOOL GetMappingInfoByName(const char* name, /* out */ std::string& texFileName);

		//! Collision with a ray.
		BOOL CollideWithRay(D3DXVECTOR3& pos, float x, float y, float z, D3DXVECTOR3& dir);

		//! Fill texture map with specified color.
		BOOL FillTextureMapA8R8G8B8(const char* name, DWORD color);
		BOOL FillTextureMapR32F(const char* name, float color);
		BOOL FillTextureMapL8(const char* name, BYTE color);

		//! Get texture map by map name.
		CTexture2D* GetTextureMap(const char* name, BOOL isLayer);

		//! Render this terrain region.
		void Render();

		//! Render shadow.
		void RenderShadow(D3DXMATRIX& matView, D3DXMATRIX& matProj);

	private:
		int __DecideLayer(const char* fileName);
		BOOL __CheckLayerEmpty(int layer);
		void __RemoveTexture(CTexture2D* tex);
		const char* __GetTechniqueName();

	private:
		CEntityTerrain* _pEntityTerrain;
		CTerrainRegion* _coreTerrainRegion;

		CHardwareBuffer* _vbPosition;
		CHardwareBuffer* _vbNormal;
		CHardwareBuffer* _vbUV;
		CHardwareBuffer* _ibIndex;

		CRenderInput* _renderInput;
		CRenderInput* _renderInputShadow;

		CShader* _shader;

		std::vector<CTexture2D*> _vecTexture;

		CTextureMapping _mapping;
		CTextureMapping _layerMapping;

		DWORD _regionX;
		DWORD _regionY;
	};
};

#endif // __H_MK_REPR_TERRAIN_REGION__